package edu.pku.sei.modeler.editparts;

import java.beans.PropertyChangeEvent;
import java.util.Iterator;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.palette.ConnectionCreationToolEntry;
import org.eclipse.gef.palette.CreationToolEntry;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.tools.DragEditPartsTracker;

import edu.pku.sei.modeler.editpolicies.UMLDiagramGraphicalNodeEditPolicy;
import edu.pku.sei.modeler.figures.CommentFigure;
import edu.pku.sei.modeler.handler.ActionHandleManager;
import edu.pku.sei.modeler.model.common.AbstractFactory;
import edu.pku.sei.modeler.model.common.ModelRegistry;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.structure.MetaShapeElement;
import edu.pku.sei.modeler.model.structure.StructureFactory;
import edu.pku.sei.modeler.model.uml.Kernel.Comment;
import edu.pku.sei.modeler.ui.palette.MetaCreationFactory;
import edu.pku.sei.modeler.uml.images.ImageProvider;
import edu.pku.sei.modeler.uml.modelHelper.ModelPackage;

public class CommentEditpart extends AbstractUMLNodeEditPart {

	public CommentEditpart(MetaShapeElement model) {
		super(model);
	}

	private Comment getModelElement() {
		return (Comment) ((MetaNode) getModel()).getModelElement();
	}

	@Override
	protected IFigure createFigure() {
		return new CommentFigure();
	}

	@Override
	protected IFigure getDirectEditFigure() {
		return ((CommentFigure) this.getFigure()).getTextFigure();
	}

	@Override
	protected DirectEditPolicy createDirectEditPolicy() {
		return new DirectEditPolicy() {
			protected Command getDirectEditCommand(DirectEditRequest request) {
				return new ChangeCommentContentCommand(getModelElement(),
						(String) request.getCellEditor().getValue());
			}

			protected void showCurrentEditValue(DirectEditRequest request) {
				IFigure fig = getDirectEditFigure();
				if (fig instanceof Label) {
					((Label) fig).setText(getModelElement().getBody());
					fig.getUpdateManager().performUpdate();
				}
			}
		};
		// return null;
	}

	@Override
	protected void createEditPolicies() {
		super.createEditPolicies();
		installActionHandle();
	}

	public DragTracker getDragTracker(Request request) {
		return new DragEditPartsTracker(this) {
			@Override
			protected void updateTargetRequest() {
				super.updateTargetRequest();
			}
			
			protected Command getCommand() {
				CompoundCommand command = new CompoundCommand();
				Iterator iter = getOperationSet().iterator();
				Request request = getTargetRequest();
				request.setType(REQ_MOVE);
				while (iter.hasNext()) {
					EditPart editPart = (EditPart)iter.next();
					command.add(editPart.getCommand(request));
				}
				return command;
			}
		};
	}
	
	/**
	 * Install Action handles for this editPart.
	 */
	private void installActionHandle() {
		// Install mouse hover
		ActionHandleManager actionMngr = new ActionHandleManager(this);
		// Create a toolbar of actions.
		PaletteDrawer entries = new PaletteDrawer("creation tool");

		try {
			AbstractFactory modelFactory = ModelRegistry.getRegistry()
					.getFactory(this.getNode().getModel());
			StructureFactory sFactory = (StructureFactory) ModelRegistry
					.getRegistry().getStructureFactory(
							this.getNode().getModel());

			CreationToolEntry commentLinkToolEntry = new ConnectionCreationToolEntry(
					ImageProvider.DEPENDENCY_IMAGE,
					"Link",
					new MetaCreationFactory(false, ModelPackage.__DEPENDENCY__,
							modelFactory, sFactory),
					ImageProvider
							.getImageDescriptor(ImageProvider.DEPENDENCY_IMAGE),
					null);

			entries.add(commentLinkToolEntry);

		} catch (Exception e) {
		}
		actionMngr.addTool(entries, PositionConstants.EAST, false, 5);

	}

	@Override
	protected void handlePropertyChanged(PropertyChangeEvent event) {
		refreshVisuals();
		super.handlePropertyChanged(event);
	}

	@Override
	protected void refreshVisuals() {

		CommentFigure commentFigure = (CommentFigure) this.getFigure();
		commentFigure.setComment(getModelElement().getBody());

		super.refreshVisuals();
	}

	private class ChangeCommentContentCommand extends Command {

		private String newCommentContent;

		private String oldCommentContent;

		private Comment comment;

		public ChangeCommentContentCommand(Comment modelElement, String string) {
			this.comment = modelElement;
			this.oldCommentContent = modelElement.getBody();
			this.newCommentContent = string;
		}

		@Override
		public void execute() {
			comment.setBody(this.newCommentContent);
		}

		@Override
		public void undo() {
			comment.setBody(this.oldCommentContent);
		}

		@Override
		public boolean canExecute() {
			return comment != null;
		}

	}

}
